#include <cstdlib>
#include <ctime>
#include <iostream>

#include "Game.h"


using namespace std;

/**
 * Constructor
 * @see Reset()
 */
Game::Game()
{
	reset();
}


/**
 * Destructor
 * @see freeMonstersInformation()
 */
Game::~Game()
{
	freeMonstersInformation();
	freeClassInformation();
	freeItemsInformation();
	freeLevelingInformation();
	// FREE OTHER COMPONENTS HERE TOO
}


/**
 * Resets the Game
 * set player position to 0
 * points the map pointer to NULL
 * creates a new Player instance
 * Initializes the map with the first loaded map described in the XML config file
 * Set State to Main Menu
 * @see checkMapInformation()
 * @param void
 * @return void
 */
void Game::reset()
{
	srand((unsigned int)time(0));
	m_playerCoord.x = 0;
	m_playerCoord.y = 0;
	m_currentMap = NULL;
	m_player = new Player;
	checkMapInformation();
	m_iState = GAME_STATE_MAIN;
}


/**
 * Load all the data of the game
 * @see loadLevelingInformation()
 * @see loadMonstersInformation()
 * @see loadItemsInformation()
 * @see loadItemsForMonsters()
 * @see loadMapInformation()
 * @see checkMapInformation()
 * @see loadClassInformation()
 * @param void
 * @return bool - false if there is an error
 */
bool Game::load()
{
	loadLevelingInformation();
	loadMonstersInformation();
	loadItemsInformation();
	loadItemsForMonsters();
	loadMapInformation();
	if (!checkMapInformation())
	{
		return false;
	}
	loadClassInformation();
	return true;
}


/**
 * Prints the Intro screen
 * @param void
 * @return void
 */
void Game::printBanner()
{
	cout << "-_____" << endl;
	cout << "  ' | -,          _     _" << endl;
	cout << " /| |  |` ,._-_  < \\,  / \\\\  /'\\\\ \\\\/\\\\ " << endl;
	cout << " || |==||  ||    /-|| || || || || || || " << endl;
	cout << "~|| |  |,  ||   (( || || || || || || || " << endl;
	cout << " ~-____,   \\\\,   \\/\\\\ \\\\_-| \\\\,/  \\\\ \\\\ " << endl;
	cout << "(                      /  \\             " << endl;
	cout << "                      '----`" << endl;
 	cout << "_" << endl;    
	cout << "- - /, /," << endl;
	cout << "  )/ )/ )   _                '" << endl;
	cout << "  )__)__)  < \\, ,._-_ ,._-_ \\\\  /'\\\\ ,._-_ " << endl;
	cout << " ~)__)__)  /-||  ||    ||   || || ||  ||" << endl;
	cout << "  )  )  ) (( ||  ||    ||   || || ||  ||" << endl;
	cout << " /-_/-_/   \\/\\\\  \\\\,   \\\\,  \\\\ \\\\,/   \\\\," << endl;
	cout << endl << endl << endl ;
	cout << "A console adaptation of the RPG ."<< endl;
	cout << "By D3vN0ll"<< endl;
	cout << endl << endl << endl ;
	system("pause");
	system("cls");
}


/**
 * Launch the Playre Character creation process
 * @see Player::generate()
 * @param void
 * @return void
 */
void Game::generateCharater()
{
	if (m_vecMaxXPperLevel.size() >= 1)
	{
		m_player->generate(m_classes, m_items, m_vecMaxXPperLevel[0]);
	}
	else
	{
		cout << "Error: No leveling information available to generate Character." << endl;
	}
}


/**
 * Saves the current Player Character
 * and changes the game state to continue playing
 * @see Player::Save()
 * @param void
 * @return void
 */
void Game::saveGame()
{
	m_player->Save(PLAYER_SAVEFILE_FILENAME);
	cout << "Character is saved." << endl;
	system("pause");
	system("cls");
	m_iState = GAME_STATE_PLAY;
}


/**
 * Loads the Saved Character
 * and changes the game state to continue playing
 * @see Player::Load()
 * @param void
 * @return void
 */
void Game::loadGame()
{
	m_player->Load(PLAYER_SAVEFILE_FILENAME, m_classes);
	cout << "Character is loaded." << endl;
	system("pause");
	system("cls");
	m_iState = GAME_STATE_PLAY;
}


/**
 * This is the mainLoop of the game.
 * States flow are explained in the "State Machine Diagram" on the Website.
 * @see processMainMenu()
 * @see printMainMenu()
 * @see loadGame()
 * @see saveGame()
 * @see processGameMenu()
 * @see printGameMenu()
 * @see Rest()
 * @see processMoveMenu()
 * @see printMoveMenu()
 * @see processEquipMenu()
 * @see printEquipMenuPlace()
 * @see printEquipMenuItem()
 * @see print()
 * @param void
 * @return int - return 0 when finished
 */
int Game::mainLoop()
{
	printBanner();
	while (m_iState != GAME_STATE_QUIT)
	{
		switch (m_iState)
		{
		case GAME_STATE_MAIN:
			processMainMenu(printMainMenu());
			break;
		case GAME_STATE_NEW:
			generateCharater();
			m_iState = GAME_STATE_PLAY;
			break;
		case GAME_STATE_LOAD:
			loadGame();
			break;
		case GAME_STATE_SAVE:
			saveGame();
			break;
		case GAME_STATE_PLAY:
			processGameMenu(printGameMenu());
			break;
		case GAME_STATE_REST:
			m_player->Rest();
			m_iState = GAME_STATE_PLAY;
			break;
		case GAME_STATE_MOVE:
			m_iState = GAME_STATE_PLAY;
			processMoveMenu(printMoveMenu());
			break;
		case GAME_STATE_EQUIPITEM:
			if (m_player->getNumItemInEquipment() > 0)
			{
				processEquipMenu(printEquipMenuPlace(), printEquipMenuItem());
			}
			else
			{
				cout << "You do not have any equipment." << endl;
				system("pause");
			}
			system("cls");
			m_iState = GAME_STATE_PLAY;
			break;
		case GAME_STATE_PRINTCHAR:
			m_player->print();
			m_iState = GAME_STATE_PLAY;
			break;
		case GAME_STATE_PRINTHELP:
			printHelp();
			m_iState = GAME_STATE_PLAY;
			break;
		case GAME_STATE_QUIT:
			cout << "[Thank you for playing]" << endl;
			system("pause");
		default:
			system("cls");
			break;
		}
	}
	return 0;
}






